Skip to content

Support number-keyed records in record() and Describe#1297

Open
ATOM00blue wants to merge 1 commit into
ianstormtaylor:mainfrom
ATOM00blue:fix/record-number-key
Open

Support number-keyed records in record() and Describe#1297
ATOM00blue wants to merge 1 commit into
ianstormtaylor:mainfrom
ATOM00blue:fix/record-number-key

Conversation

@ATOM00blue
Copy link
Copy Markdown

Closes #929

Describe<Record<number, number>> currently produces a TypeScript compile error because record() is typed K extends string and the StructSchema inference (via IsRecord) only collapses string-indexed records to a null schema. Number-keyed records fell through to the object-schema branch, so the inferred schema ({ [x: number]: Describe<number> }) didn't match record()'s null schema.

Changes

  • Broaden record<K extends string, V> to record<K extends string | number, V>.
  • Broaden IsRecord<T> to also match when number extends keyof T, so Describe<Record<number, V>> resolves to a record struct schema.

String-keyed Record behaviour is unchanged, and numeric-literal-keyed object types (e.g. { 0: string }) still correctly resolve to object schemas. Added type tests in test/typings/describe.ts and test/typings/record.ts.

Broaden record() to accept a number-keyed struct and update the
StructSchema inference (via IsRecord) so that Describe<Record<number, V>>
resolves to a record struct schema instead of an object schema. This
fixes the TypeScript compile error when typing a number-keyed Record,
while leaving string-keyed Record behaviour unchanged.
Copilot AI review requested due to automatic review settings May 21, 2026 03:16
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Extends record() and related type utilities/tests to support numeric keys (Record<number, V>) in addition to string keys.

Changes:

  • Add typings tests for Record<number, number> and Describe<Record<number, number>>.
  • Broaden IsRecord to accept types with number keys.
  • Widen record()’s generic key constraint from string to string | number.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
test/typings/record.ts Adds typings coverage for record(number(), number()) returning Record<number, number>.
test/typings/describe.ts Adds typings coverage for describing Record<number, number>.
src/utils.ts Updates IsRecord conditional type to include numeric-keyed records.
src/structs/types.ts Updates record() signature to allow `K extends string

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/structs/types.ts
Comment on lines +367 to 370
export function record<K extends string | number, V>(
Key: Struct<K>,
Value: Struct<V>
): Struct<Record<K, V>, null> {
Comment thread src/utils.ts
Comment on lines 242 to 248
export type IsRecord<T> = T extends object
? string extends keyof T
? T
: never
: number extends keyof T
? T
: never
: never
Comment thread test/typings/record.ts
return x
})

test<Record<number, number>>((x) => {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Type null is not assignable error with number keyed Record

2 participants